package com.songtech.base.aspect;

import java.lang.reflect.Array;
import java.lang.reflect.Method;
import java.util.Collection;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;

import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.Signature;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Pointcut;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.web.bind.annotation.ResponseBody;

import com.songtech.base.common.BaseConstant;
import com.songtech.base.exception.BusinessException;

/**   
 * @ClassName:  ResponeAspect   
 * @Description:数据返回切面在这
 * @author: denggang 
 *     
 * @Copyright: 2018 All rights reserved. 
 */
//@Component
//@Aspect
public class ResponeAspect {
	
	private static Logger log = LoggerFactory.getLogger(ResponeAspect.class);
	
	/**
	 * 业务返回值
	 */
	private static String data = "data";
	/**
	 * 当前业务执行状态码
	 * 返回编码1、成功；0、失败
	 */
	private static String code = "code";
	/**
	 * 如果执行错误返回错误信息
	 */
	private static String msg = "msg";
	/**
	 * 返回时间
	 */
	private static String date = "date";
	
	@Pointcut("execution(* com.songtech..controller..*Controller*.*(..))")
	public void aspect(){
		
	}
	
	/**
	 * <p>
	 * 拦截有ResponseBody注解,且ApiResult会自动附加上接口公共属性
	 * </p>
	 * @param arg0
	 * @return
	 * @throws Throwable
	 */
	@Around("aspect()")
	public Object invoke(ProceedingJoinPoint joinPoint) throws Throwable {
		Signature signature = joinPoint.getSignature();
		String methodName = signature.getName();
		Object retVal = null;
		
		Method [] methods = joinPoint.getTarget().getClass().getMethods();
//		Object args[] = joinPoint.getArgs();
		Method method =  null;
		for(Method temp : methods){
			if(methodName.equals(temp.getName())){
				method = temp;
				break;
			}
		}
		String className = joinPoint.getTarget().toString();
		if(!this.isEmpty(className)) {
			className = className.substring(className.lastIndexOf(".")+1);
		}
		
		log.info("Api请求：{}类：{} 方法", joinPoint.getTarget(), methodName);
		
		Map<String,Object> resultMap = null;
		if(method == null){
			resultMap = new HashMap<>();
			resultMap.put(code, BaseConstant.FAIL_CODE);
			resultMap.put(msg, "");
			resultMap.put(data, "请求接口异常：没有取得方法！");
			return retVal;
		}
		//如果方法没有用ResponseBody标记，则认为是正常返回
		if(!method.isAnnotationPresent(ResponseBody.class)){
			retVal = joinPoint.proceed();
			return retVal;
        }
		//存在ApiResult注解
		if(method.isAnnotationPresent(ResponseBody.class)){
			//返回json格式的数据
			resultMap = new HashMap<>();
			resultMap.put(code, BaseConstant.SUCCESS_CODE);
			resultMap.put(msg, "");
			resultMap.put(data, "");
			resultMap.put(date, new Date());
			try {
				retVal = joinPoint.proceed();
				resultMap.put(data, retVal);
			} catch (BusinessException e) {
				resultMap.put(code, e.getCode());
				resultMap.put(msg, e.getMessage());
				resultMap.put(data, "");
			} catch (IllegalArgumentException e) {
				resultMap.put(code, BaseConstant.FAIL_CODE);
				resultMap.put(msg, e.getMessage());
			} catch(Exception e){
				resultMap.put(code, BaseConstant.FAIL_CODE);
				log.error("系统发生异常:", e);
				resultMap.put(msg, "系统异常，请稍后再试！\n错误信息:"+e.getMessage());
			}
			return resultMap;
		}
		return joinPoint.proceed();
	}
	
	/**
	 * 判断对象是否为空.
	 * 
	 * <pre>
	 * 如果obj为字符串,且全部为空白字符,则返回true. 
	 * 如果是数组,则0长度的数组也视为空.
	 * Collection/Map则直接返回isEmpty()
	 * </pre>
	 * 
	 * @param obj
	 * @return
	 */
	public boolean isEmpty(Object obj) {
		if (obj == null) {
			return true;
		}
		if (obj instanceof String) {
			// 字符串判断是否为0字节或全空白
			return ((String) obj).trim().length() == 0;
		}
		if (obj instanceof StringBuilder || obj instanceof StringBuffer) {
			// 同字符串
			return obj.toString().trim().length() == 0;
		}
		if (obj instanceof CharSequence) {
			// CharSequence
			return ((CharSequence) obj).length() == 0;
		}

		if (obj.getClass().isArray()) {
			// 数组
			return Array.getLength(obj) == 0;
		}
		if (obj instanceof Collection) {
			// 集合
			return ((Collection<?>) obj).isEmpty();
		}
		if (obj instanceof Map) {
			// Map
			return ((Map<?, ?>) obj).isEmpty();
		}
		if(obj instanceof Set) {
			//set
			return ((Set<?>) obj).isEmpty();
		}
		return false;
	}

}
